介绍
MVVM,Model-View-ViewModel,与上次讲的MVP模式比较的类似,MVP中需要大量的接口文件,而MVVM模式下,View和ViewModel直接关联,使用上比较方便,简化了代码.大致的结构图如下:
可以看待View和ViewModel是双向的交互,这一点很关键
DataBinding
Data Binding Library是Google推出的,可以说是针对MVVM模式的支持库,通过在Layout中进行数据的访问,来实现View和Data的双向绑定。不仅使用灵活,用法丰富,而且支持也是相当的广泛,很大程度上降低了代码量和耦合性,减少了开发者的压力。
build.gradle
1 2 3
| dataBinding { enabled= true }
|
这样使用比较的方法,当然这个需要当前的Gradle版本支持这个属性
Layout Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <import type="com.example.mraz.mvvmdemo.Model.User"></import> <variable name="user" type="User"> </variable> </data> <LinearLayout ... </LinearLayout> </layout>
|
最完成使用Layout属性,通过data属性值,添加需要在布局文件中使用的变量和对应的变量类型,也可以先import文件,然后直接使用,不然就需要在type中使用类型的完整路径,当遇到相同的类名的时候,DataBinding支持别名的定义,alias
Layout Access Data
布局文件文件中如何实现对绑定数据的访问
1 2 3 4 5 6 7 8 9 10 11
| <TextView android:id="@+id/tv_username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.getUsername()}" />
<TextView android:id="@+id/tv_password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.getPassword()}" />
|
使用格式为“@{ }”,大括号中的使用方式与代码中的基本无差别,可以使用方法,也可以使用对应的成员变量,当然如果权限允许的话,如果要直接访问private变量或者方法,显然是不现实的。
Activity Set Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class MainActivity extends AppCompatActivity { User user = new User("", ""); @Bind(R.id.et_username) EditText etUsername; @Bind(R.id.et_password) EditText etPassword; @Bind(R.id.tv_username) TextView tvUsername; @Bind(R.id.tv_password) TextView tvPassword;
ActivityMainBinding activityMainBinding;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); ButterKnife.bind(this); }
@OnTextChanged(value = R.id.et_username, callback = OnTextChanged.Callback.TEXT_CHANGED) void onUserNameChanged(CharSequence s,int start,int before,int count) { user.setUsername(s.toString()); activityMainBinding.setUser(user); }
@OnTextChanged(value = R.id.et_password, callback = OnTextChanged.Callback.TEXT_CHANGED) void onPasswordChangedps(CharSequence s,int start,int before,int count) { user.setPassword(s.toString()); activityMainBinding.setUser(user); }
}
|
几个关键点:
- ActivityMainBinding activityMainBinding
这里定义的变量类型ActivityMainBinding 与布局文件对应
activity_main ——-> ActivityMainBinding
first_second ——-> FirstSecondingBinding
Binding类的命名是基于所述layout文件的名称,用大写开头,除去下划线()以及()后的第一个字母大写,然后添加“Binding”后缀。这个类将被放置在一个模块封装包里的databinding封装包下 Binding类可通过调整data元素中的class属性来重命名或放置在不同的包中。例如:
1 2 3
| <data class="UserBinding"> ... </data>
|
- activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
获取ActivityMainBinding对象,用于后面设置变量
activityMainBinding.setUser(user);设置数据,User变量
表达式
常用的表达式和正常的java代码比较类似
- 数学 + - / * %
- 字符串连接 +;
- 逻辑 && ||
- 二进制 & | ^
- 一元运算 + - ! ~
- 移位 >> >>> <<
- 比较 == > < >= <=
- instanceof
- 分组 ()
- Cast
- 方法调用
- 数据访问 []
- 三元运算 ?:
不支持的操作
this
super
new
显式泛型调用
实际效果图
备注:
关于DataBinding,这里有一篇文章讲得很清晰,推荐一下
https://segmentfault.com/a/1190000002876984
效果图对应的代码贴了一部分,实现相对比较容易,这里就不赘述了,如果有需要的留言,我再附上。